/**
 * 
 */
package edu.unipd.p2t.communicaton;

import java.io.IOException;
import java.util.HashSet;

import android.util.Log;

import edu.unipd.p2t.db.DataManager;
import edu.unipd.p2t.db.Message;

/**
 * @author Tommaso Dal Sasso
 *
 */
public class CommunicationManager {

	/**
	 * The connection manager to manage physical connection to other devices
	 */

	private static final DataManager dataManager = null;
	private static CommunicationManager instance = new CommunicationManager();

	public final String TAG = "p2t";


	/**
	 * 
	 */
	private CommunicationManager() {}

	public static CommunicationManager getInstance() {
		return instance;
	}


	/**
	 * Synchronizes the message lists of the two devices
	 * @return returns an array containing the messages missing in the remote device
	 */
	public HashSet<String> sync( p2tDevice dev ) {

		// ricavo l'hash dei miei messaggi
		HashSet<String>
		remoteHashList,
		myHashList = new HashSet<String>();

		for( String hash : dataManager.getHash() )
			myHashList.add( hash );

		try {

			if( dev.isFirst() ) {
				// receiving data
				remoteHashList = dev.receiveIdList();
				// sending data
				dev.sendHashList( myHashList );
			} else {
				// sending data
				dev.sendHashList( myHashList );
				// receiving data
				remoteHashList = dev.receiveIdList();
			}

		} catch( IOException e ) {
			Log.e(TAG, "error transmitting messages hash");
			// returning empty set
			return new HashSet<String>();
		}

		// removing messages that remote device already got
		for( String hash : myHashList ) {
			remoteHashList.remove( hash );
		}
		return remoteHashList;
	}


	/**
	 * Performs the actions needed to receive and store incoming messages
	 * @param dev the remote device
	 * @throws IOException
	 */
	private void receiveAndStoreMessages( p2tDevice dev ) throws IOException {
		Message[] receivedMessages = dev.receiveMessages();
		for( Message m: receivedMessages ) {
			dataManager.insMessage( m );
		}
	}


	private Message[] getMessageByHash( HashSet<String> messagesHash ) {
		Message[] messages = new Message[ messagesHash.size() ];
		int size = 0;

		for( String mh: messagesHash ) {
			messages[ size ] = dataManager.getMessage( mh );
			size++;
		}
		return messages;
	}

	/**
	 * Method to syncronyze
	 * @param dev
	 */
	public void newConnectedDevice( final p2tDevice dev ) {

		// create a new Thread to handle the communication
		new Thread() {

			@Override
			public void run() {

				// sync the message list between the two devices
				HashSet<String> messagesHash = sync( dev );

				try {
					if( dev.isFirst() ) { // the remote device is the first to transmit

						// first receive
						receiveAndStoreMessages( dev );
						// then transmit
						dev.sendMessages( getMessageByHash( messagesHash ) );

					} else { // I am the first to transmit

						// first transmit
						dev.sendMessages( getMessageByHash( messagesHash ) );
						// then receive
						receiveAndStoreMessages( dev );

					}
				} catch( IOException e ) { Log.e(TAG, "error transmitting messages");}
				finally {
					// closing connection
					dev.close();
				}
			}

		}.start();
	}

}
